#include "widget_encoder.h"
#include "utils.h"
#include <iostream>
#include <sstream>
#include <string>
#include <utility>

#define TABLE_1 "    "
#define TABLE_2 "        "
#define TABLE_3 "            "
using namespace std;

template<typename T>
inline void value(ostream &ss, string key, T &&value) {
    ss << key << ": " << std::forward<T>(value) << "," << endl;
}

std::string dymy::Text::generateTextStyle() const {
    const dymy::Text &text = *this;
    stringstream ss;
    ss << "TextStyle(" << endl;
    writeTextStyle(ss, TABLE_1);
    ss << TABLE_1 << ")," << endl; /// textStyle
    return ss.str();
}

void dymy::Text::writeTextStyle(std::stringstream &ss,
                                const char *table) const {
    const dymy::Text &text = *this;

    if (text.font_weight) {
        value(ss << table, "fontWeight",
              "FontWeight.w" + to_string(*text.font_weight));
    }
    if (text.font_size) {
        value(ss << table, "fontSize", *text.font_size);
    }
    if (text.line_height) {
        value(ss << table, "height", *text.line_height);
    }
    if (text.letter_space) {
        value(ss << table, "letterSpacing", *text.letter_space);
    }
    if (text.color) {
        std::string colorCode;
        switch (*text.color) {
            case 0xFF66A6FF:
                colorCode = "YvrColors.buttonStart";
                break;
            case 0XFF6D78F2:
                colorCode = "YvrColors.buttonEnd";
                break;
            case 0XFFEEEEEE:
                colorCode = "YvrColors.buttonDisable";
                break;
            case 0XFF4F7FFE:
                colorCode = "YvrColors.standard";
                break;
            case 0XFFF14E4E:
                colorCode = "YvrColors.warning";
                break;
            case 0XFF55CE13:
                colorCode = "YvrColors.success";
                break;
            case 0XFFFFFFFF:
                colorCode = "YvrColors.background";
                break;
            case 0XFFF5F7FA:
                colorCode = "YvrColors.backgroundSecondary";
                break;
            case 0XFFF0F2F5:
                colorCode = "YvrColors.backgroundItem";
                break;
            case 0XFF2C2E33:
                colorCode = "YvrColors.textTitle";
                break;
            case 0XFF6E7380:
                colorCode = "YvrColors.textSub";
                break;
            case 0XFFAFB6CC:
                colorCode = "YvrColors.textWeak";
                break;
            default:
                stringstream c;
                c << "Color(" << dymy::to_color(*text.color) << ")";
                colorCode = c.str();
                break;
        }

        value(ss << table, "color", colorCode);
    }
    if (text.font_family) {
        value(ss << table, "fontFamily", *text.font_family);
    }
}

std::string dymy::Text::generateCode() const {
    const dymy::Text &text = *this;
    stringstream ss;
    ss << "Text(" << endl;
    ss << TABLE_1 << "'" << text.text << "'" << ',' << endl;
    ss << TABLE_1 << "style:TextStyle(" << endl;
    writeTextStyle(ss, TABLE_2);
    ss << TABLE_1 << ")," << endl; /// textStyle
    ss << ")," << endl;            /// text

    return ss.str();
}

std::string dymy::Container::generateCode() const {
    const dymy::Container &container = *this;
    stringstream ss;
    ss << "Container(" << endl;
    if (container.padding) {
        stringstream p;

        const EdgeInsets &edge = container.padding.value();
        if (edge.left == edge.top && edge.top == edge.right &&
            edge.right == edge.bottom) {
            p << "EdgeInsets.all(" << edge.left << ")";
        } else if (edge.left == edge.right && edge.top == edge.bottom) {
            p << "EdgeInsets.symmetric(horizontal: " << edge.left
              << ",vertical: " << edge.top << ")";
        } else {
            p << "EdgeInsets.only(left: " << edge.left << ",top: " << edge.top
              << ",right: " << edge.right << ",bottom: " << edge.bottom << ")";
        }
        value(ss << TABLE_2, "padding", p.str());
    }
    ss << TABLE_1 << "decoration:BoxDecoration(" << endl;
    if (container.border_radius) {
        value(ss << TABLE_2, "borderRadius",
              "BorderRadius.circular(" + to_string(*container.border_radius) + ")");
    }
    if (container.border) {
        ss << TABLE_2 << "border:Border.all(" << endl;

        stringstream c;
        c << "Color(" << dymy::to_color(container.border->border_color) << ")";
        value(ss << TABLE_3, "color", c.str());

        value(ss << TABLE_3, "width", container.border->border_width);

        ss << TABLE_2 << ")," << endl;
    }

    if (container.background) {
        stringstream c;
        c << "Color(" << dymy::to_color(container.background.value()) << ")";
        value(ss << TABLE_2, "color", c.str());
    }
    ss << TABLE_1 << ")," << endl; /// textStyle
    ss << ")," << endl;            /// text

    return ss.str();
}